package npap.cater.unr.edu.client.scaffold;

import npap.cater.unr.edu.client.domain.Project;
import npap.cater.unr.edu.client.managed.activity.*;
import npap.cater.unr.edu.client.managed.request.ApplicationEntityTypesProcessor;
import npap.cater.unr.edu.client.managed.request.ApplicationRequestFactory;
import npap.cater.unr.edu.client.managed.ui.customized.CustomizedApplicationDetailsActivities;
import npap.cater.unr.edu.client.managed.ui.customized.CustomizedApplicationMasterActivities;
import npap.cater.unr.edu.client.proxy.ProjectProxy;
import npap.cater.unr.edu.client.scaffold.customizedutil.ProjectComparator;
import npap.cater.unr.edu.client.scaffold.gae.GaeHelper;
import npap.cater.unr.edu.client.scaffold.place.*;
import npap.cater.unr.edu.client.scaffold.place.ProxyPlace.Operation;
import npap.cater.unr.edu.client.scaffold.place.customized.AppPlace;
import npap.cater.unr.edu.client.scaffold.place.customized.AppPlaceToProjectListPlace;
import npap.cater.unr.edu.client.scaffold.place.customized.ProjectListPlace;
import npap.cater.unr.edu.client.scaffold.place.customized.ProjectListPlacePicker;
import npap.cater.unr.edu.client.scaffold.request.RequestEvent;
import com.google.gwt.activity.shared.*;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.logging.client.LogConfiguration;
import com.google.gwt.place.shared.*;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.LoggingRequest;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasConstrainedValue;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.inject.Inject;
import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryLogHandler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * Application for browsing entities.
 */
public class ScaffoldDesktopApp extends ScaffoldApp {
	private static final Logger LOGGER = Logger.getLogger(Scaffold.class.getName());
	/**
	 * @uml.property  name="shell"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private final ScaffoldDesktopShell shell;
	/**
	 * @uml.property  name="requestFactory"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private final ApplicationRequestFactory requestFactory;
	/**
	 * @uml.property  name="eventBus"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private final EventBus eventBus;
	/**
	 * @uml.property  name="placeController"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private final PlaceController placeController;
	/**
	 * @uml.property  name="placeHistoryFactory"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private final PlaceHistoryFactory placeHistoryFactory;
	/**
	 * @uml.property  name="applicationMasterActivities"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private final CustomizedApplicationMasterActivities applicationMasterActivities;
	/**
	 * @uml.property  name="applicationDetailsActivities"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private final CustomizedApplicationDetailsActivities applicationDetailsActivities;
	/**
	 * @uml.property  name="applicationRooMasterActivities"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private final ApplicationRooMasterActivities applicationRooMasterActivities;

	@Inject
	public ScaffoldDesktopApp(ScaffoldDesktopShell shell, ApplicationRequestFactory requestFactory, EventBus eventBus, PlaceController placeController, PlaceHistoryFactory placeHistoryFactory, ApplicationRooMasterActivities applicationRooMasterActivities, CustomizedApplicationMasterActivities applicationMasterActivities, CustomizedApplicationDetailsActivities applicationDetailsActivities, GaeHelper gaeHelper) {
		this.shell = shell;
		this.requestFactory = requestFactory;
		this.eventBus = eventBus;
		this.placeController = placeController;
		this.placeHistoryFactory = placeHistoryFactory;
		this.applicationMasterActivities = applicationMasterActivities;
		this.applicationDetailsActivities = applicationDetailsActivities;
		this.applicationRooMasterActivities=applicationRooMasterActivities;
	}

	public void run() {
		/* Add handlers, setup activities */
		init();

		/* Hide the loading message */
		Element loading = Document.get().getElementById("loading");
		loading.getParentElement().removeChild(loading);

		/* And show the user the shell */
		RootLayoutPanel.get().add(shell);
	}

	private void init() {
		GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
			public void onUncaughtException(Throwable e) {
				Window.alert("Error: " + e.getMessage());
				LOGGER.log(Level.SEVERE, e.getMessage(), e);
			}
		});

		if (LogConfiguration.loggingIsEnabled()) {
			// Add remote logging handler
			RequestFactoryLogHandler.LoggingRequestProvider provider = new RequestFactoryLogHandler.LoggingRequestProvider() {
				public LoggingRequest getLoggingRequest() {
					return requestFactory.loggingRequest();
				}
			};
			Logger.getLogger("").addHandler(new RequestFactoryLogHandler(provider, Level.WARNING, new ArrayList<String>()));
		}

		RequestEvent.register(eventBus, new RequestEvent.Handler() {
			// Only show loading status if a request isn't serviced in 250ms.
			private static final int LOADING_TIMEOUT = 250;

			public void onRequestEvent(RequestEvent requestEvent) {
				if (requestEvent.getState() == RequestEvent.State.SENT) {
					shell.getMole().showDelayed(LOADING_TIMEOUT);
				} else {
					shell.getMole().hide();
				}
			}
		});
		//Project List Master
		
		
		AppPlaceToProjectListPlace appPlaceToListPlace = new AppPlaceToProjectListPlace(placeController);
		ProjectListPlacePicker projectListPlacePicker = new ProjectListPlacePicker(placeController, appPlaceToListPlace, requestFactory);
		HasConstrainedValue<ProjectListPlace> projectListPlacePickerView = shell.getProjectPlacesBox();
		projectListPlacePickerView.setAcceptableValues(getTopProjectPlaces());
		HasConstrainedValue<ProxyListPlace> listPlacePickerView = shell.getPlacesBox();
		projectListPlacePicker.register(eventBus, projectListPlacePickerView);
		//end of project list master
		
				
		CachingActivityMapper cached = new CachingActivityMapper(applicationMasterActivities);
		ProxyPlaceToListPlace proxyPlaceToListPlace = new ProxyPlaceToListPlace();
		
		
//		ActivityMapper masterActivityMap = new FilteredActivityMapper(proxyPlaceToListPlace, cached);
//		ActivityMapper masterActivityMap = new FilteredActivityMapper(projectPlaceToListPlace, cached);
		ActivityMapper masterActivityMap = new FilteredActivityMapper(appPlaceToListPlace, cached);
		final ActivityManager masterActivityManager = new ActivityManager(masterActivityMap, eventBus);

		masterActivityManager.setDisplay(shell.getMasterPanel());
		

		ProxyListPlacePicker proxyListPlacePicker = new ProxyListPlacePicker(placeController, proxyPlaceToListPlace, requestFactory);
//		HasConstrainedValue<ProxyListPlace> listPlacePickerView = shell.getPlacesBox();
		listPlacePickerView.setAcceptableValues(getTopPlaces());
		proxyListPlacePicker.register(eventBus, listPlacePickerView);

		final ActivityManager detailsActivityManager = new ActivityManager(applicationDetailsActivities, eventBus);

		detailsActivityManager.setDisplay(shell.getDetailsPanel());
		
		

		/* Browser history integration */
//		ScaffoldPlaceHistoryMapper mapper = GWT.create(ScaffoldPlaceHistoryMapper.class);
//		mapper.setFactory(placeHistoryFactory);
//		PlaceHistoryHandler placeHistoryHandler = new PlaceHistoryHandler(mapper);
//		if (getTopPlaces().iterator().hasNext()) {
//			ProxyListPlace defaultPlace = getTopPlaces().iterator().next();
//			placeHistoryHandler.register(placeController, eventBus, defaultPlace);
//			placeHistoryHandler.handleCurrentHistory();
//		}
//		if (getTopProjectPlaces().iterator().hasNext()) {
//			ProjectListPlace defaultPlace = getTopProjectPlaces().iterator().next();
//			placeHistoryHandler.register(placeController, eventBus, defaultPlace);
//			placeHistoryHandler.handleCurrentHistory();
//		}
		
		
	}
	protected HashSet<ProjectListPlace> getTopProjectPlaces() {
		
		 
		 final HashSet<ProjectListPlace> rtn = new HashSet<ProjectListPlace>();
		
		requestFactory.projectRequest().findAllProjects().fire(new Receiver<List<ProjectProxy>>(){

			@Override
			public void onSuccess(List<ProjectProxy> response) {
				// TODO Auto-generated method stub
				for (int i=0;i<response.size();i++)
				{
					ProjectProxy type=response.get(i);
					Collections.sort(response, new ProjectComparator());
					rtn.add(new ProjectListPlace(type.getIdproject(),type.getProjectcName()));					
				}
				HasConstrainedValue<ProjectListPlace> projectListPlacePickerView = shell.getProjectPlacesBox();
				projectListPlacePickerView.setAcceptableValues(rtn);
				
					
				ScaffoldPlaceHistoryMapper mapper = GWT.create(ScaffoldPlaceHistoryMapper.class);
				mapper.setFactory(placeHistoryFactory);
				PlaceHistoryHandler placeHistoryHandler = new PlaceHistoryHandler(mapper);
				if (rtn.iterator().hasNext()) {
					ProjectListPlace defaultPlace = rtn.iterator().next();
					AppPlace defaultAppPlace=new AppPlace(response.iterator().next().stableId(), Operation.DETAILS ,defaultPlace.getIdProject(), defaultPlace.getProjectName());
					placeHistoryHandler.register(placeController, eventBus, defaultAppPlace);
					placeHistoryHandler.handleCurrentHistory();
				}
			}
			
		});

		return rtn;
	}
}
